package com.base.cn.platform.os.controller.statistics.flow;

import com.base.cn.platform.os.common.constants.ConfigName;
import com.base.cn.platform.os.common.controller.BaseController;
import com.base.cn.platform.os.common.utils.DateUtils;
import com.base.cn.platform.os.common.utils.ObjectUtils;
import com.base.cn.platform.os.common.utils.StringUtils;
import com.base.cn.platform.os.common.utils.http.HttpUtil;
import com.base.cn.platform.os.common.utils.result.ResultUtil;
import com.base.cn.platform.os.entity.statistics.base.StatisticsDateQueryCondition;
import com.base.cn.platform.os.entity.statistics.goods.ZStatisticsGoodsPVCount;
import com.base.cn.platform.os.entity.statistics.goods.ZStatisticsGoodsUVCount;
import com.base.cn.platform.os.entity.statistics.pvuv.ZStatisticsPageViewCount;
import com.base.cn.platform.os.entity.statistics.pvuv.ZStatisticsUniqueVisitorCount;
import com.base.cn.platform.os.service.manage.config.SysConfigService;
import com.base.cn.platform.os.service.statistics.goods.ZStatisticsGoodsPVCountBiz;
import com.base.cn.platform.os.service.statistics.goods.ZStatisticsGoodsUVCountBiz;
import com.base.cn.platform.os.service.statistics.pvuv.ZStatisticsPageViewCountBiz;
import com.base.cn.platform.os.service.statistics.pvuv.ZStatisticsUniqueVisitorCountBiz;
import com.google.gson.reflect.TypeToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 流量统计Controller
 *
 * @author s.li
 * @date 2019/04/28
 */
@RestController
@RequestMapping("/manage/statistics")
public class FlowStatisticsController extends BaseController {
    private DecimalFormat decimalFormat = new DecimalFormat("#.#");
    @Autowired
    private ZStatisticsGoodsUVCountBiz zStatisticsGoodsUVCountBiz;
    @Autowired
    private ZStatisticsGoodsPVCountBiz zStatisticsGoodsPVCountBiz;
    @Autowired
    private ZStatisticsPageViewCountBiz zStatisticsPageViewCountBiz;
    @Autowired
    private ZStatisticsUniqueVisitorCountBiz zStatisticsUniqueVisitorCountBiz;
    @Autowired
    private SysConfigService sysConfigService;

    /**
     * 录播流量统计（96K）
     * @return Map<String,Object>
     */
    @RequestMapping("/queryVideoFlowCountData")
    public Map<String,Object> queryVideoFlowCountData(@RequestBody StatisticsDateQueryCondition dateQueryCondition){
        dateQueryCondition.setTimeCondition(new Date());
        TreeMap<String,String> configMap = sysConfigService.getSysConfigContext(ConfigName.V96K);
        Map<String,String> params = new HashMap<>();
        params.put("customerKey",configMap.get("customerKey"));

        long startTime = dateQueryCondition.getStartTime().getTime()/1000L;

        long endTime = dateQueryCondition.getEndTime().getTime()/1000L;

        params.put("startTime",String.valueOf(startTime));
        params.put("endTime",String.valueOf(endTime));
        String result = null;
        try {
            result = HttpUtil.doPost(configMap.get("serviceUseInfoUrl"),params);
        } catch (IOException e) {
            logger.error("queryVideoFlowCountData()--error",e);
        }
        List<Map<String, Object>> resultMapList = new ArrayList<>();
        if(StringUtils.isNotEmpty(result)) {
            Map<String, Object> resultMap = gson.fromJson(result, new TypeToken<Map<String, Object>>() {
            }.getType());
            String code = (String) resultMap.get("code");
            if (!"0".equals(code)) {
                return null;
            }
            List<Map<String, Object>> dataList = (List<Map<String, Object>>) resultMap.get("data");
            List<Date> dateList = dateQueryCondition.getDayList();
            if (ObjectUtils.isNotEmpty(dataList)) {
                Map<String, Map<String, Object>> mapMap = dataList.stream().collect(Collectors.toMap(e -> (String) e.get("time"), em -> em));
                dateList.forEach(date -> {
                    String time = DateUtils.format(date, "yyyyMMdd");
                    Map<String, Object> map = mapMap.get(time);
                    if (ObjectUtils.isNotEmpty(map)) {
                        resultMapList.add(map);
                    } else {
                        Map<String, Object> _map = new HashMap<>();
                        _map.put("time", time);
                        _map.put("flow", 0);
                        resultMapList.add(_map);
                    }
                });
            }else{
                dateList.forEach(date -> {
                    String time = DateUtils.format(date, "yyyyMMdd");
                    Map<String, Object> _map = new HashMap<>();
                    _map.put("time", time);
                    _map.put("flow", 0);
                    resultMapList.add(_map);
                });
            }
        }
        Map<String,Object> resultMapData = ResultUtil.SUCCESS(resultMapList);
        resultMapData.put("space",0);
        resultMapData.put("useSpace",0);
        resultMapData.put("videoNum",0);
        resultMapData.put("flow",0);
        resultMapData.put("useFlow",0);
        resultMapData.put("roomNum",0);
        //获取流量、空间容量数据
        String serviceUrl = configMap.get("serviceUrl");
        try {
            result = HttpUtil.doPost(serviceUrl,params);
        } catch (IOException e) {
            logger.error("queryVideoFlowCountData()--error",e);
        }
        Map<String,Object> resultMap = null;
        if(StringUtils.isNotEmpty(result)){
            resultMap = gson.fromJson(result,new TypeToken<Map<String, Object>>(){}.getType());
        }
        if(ObjectUtils.isNotEmpty(resultMap)){
            String code = (String)resultMap.get("code");
            if("0".equals(code)){
                List<Map<String,Object>> dataList = (List<Map<String,Object>>)resultMap.get("data");
                if(ObjectUtils.isNotEmpty(dataList)){
                    Map<String,Object> flowMap = dataList.get(0);
                    //总空间
                    Double space = (Double)flowMap.get("space");
                    space = space / 1024D/ 1024D/ 1024D;
                    resultMapData.put("space",decimalFormat.format(space));
                    //已使用空间
                    Double useSpace = Double.parseDouble(flowMap.get("use_space").toString());
                    useSpace = useSpace / 1024D/ 1024D/ 1024D;
                    resultMapData.put("useSpace",decimalFormat.format(useSpace));
                    //上传视频数量
                    Double videoNum = (Double)flowMap.get("video_num");
                    resultMapData.put("videoNum",videoNum.intValue());
                    //总流量
                    Double flow = (Double)flowMap.get("flow");
                    flow = flow / 1024D/ 1024D/ 1024D;
                    resultMapData.put("flow",decimalFormat.format(flow));
                    //已使用流量
                    Double useFlow = (Double)flowMap.get("use_flow");
                    useFlow = useFlow / 1024D/ 1024D/ 1024D;
                    resultMapData.put("useFlow",decimalFormat.format(useFlow));
                    //直播房间数量
                    Double roomNum = (Double)flowMap.get("room_num");
                    resultMapData.put("roomNum",roomNum.intValue());
                }
            }
        }
        return resultMapData;
    }

    /**
     * 查询渠道分布PV分布
     * @param dateQueryCondition
     * @return ZStatisticsPageViewCount
     */
    @RequestMapping("/queryPageViewCountSpread")
    public ZStatisticsPageViewCount queryPageViewCountSpread(@RequestBody StatisticsDateQueryCondition dateQueryCondition){
        return zStatisticsPageViewCountBiz.queryPageViewCountSpread(dateQueryCondition);
    }

    /**
     * 流量看板，平台PV、UV，商品PV、UV统计数据获取<br/>
     * 平台UV，商品UV只能以最小单位为天的方式显示，PV可以按小时显示<br/>
     * 当查询条件为当天或指定某一天时，UV数据只有总量，PV可以有每个小时的明细
     * @return Map<String,Object>
     */
    @RequestMapping("/flowBulletinBoard")
    public Map<String,Object> flowBulletinBoard(@RequestBody StatisticsDateQueryCondition dateQueryCondition){
        dateQueryCondition.setTimeCondition(new Date());
        List<Date> dateList = dateQueryCondition.getDayList();
        String timeSql = StatisticsDateQueryCondition.getTimeSql(dateList,"yyyy-MM-dd");
        List<Date> date24List = null;
        if(dateList.size() ==1){
            dateQueryCondition.setType(1);
            //24小时的时间
            date24List = DateUtils.getDay24HourList(dateList.get(0));
        }
        Map<String,Object> resultMap = ResultUtil.SUCCESS();

        //平台PV
        List<ZStatisticsPageViewCount> pageViewCountList = this.pageViewCountList(dateQueryCondition.getType(),timeSql,dateList,date24List);
        resultMap.put("pageViewCountList",pageViewCountList);

        //平台UV
        List<ZStatisticsUniqueVisitorCount> uniqueVisitorCountList = this.uniqueVisitorCountList(dateList,timeSql);
        resultMap.put("uniqueVisitorCountList",uniqueVisitorCountList);

        //商品PV
        List<ZStatisticsGoodsPVCount> goodsPVCountList = this.goodsPVCountList(dateList,timeSql,date24List);
        resultMap.put("goodsPVCountList",goodsPVCountList);

        //商品UV数据
        List<ZStatisticsGoodsUVCount> goodsUVCountList = this.goodsUVCountList(dateList,timeSql);
        resultMap.put("goodsUVCountList",goodsUVCountList);

        //平台访问量(PV)
        int pvCount = pageViewCountList.stream().mapToInt(ZStatisticsPageViewCount::getPvCount).sum();
        resultMap.put("pvCount",pvCount);

        //平台访客数(UV)
        int uvCount = 0;
        if(ObjectUtils.isNotEmpty(uniqueVisitorCountList)){
            uvCount = uniqueVisitorCountList.stream().mapToInt(ZStatisticsUniqueVisitorCount::getRequestCount).sum();
        }
        resultMap.put("uvCount",uvCount);

        //商品访问量(PV)
        int goodsPVCount = goodsPVCountList.stream().mapToInt(ZStatisticsGoodsPVCount::getPvCount).sum();
        resultMap.put("goodsPVCount",goodsPVCount);

        //商品访客数(UV)
        int goodsUVCount = 0;
        if(ObjectUtils.isNotEmpty(goodsUVCountList)){
            goodsUVCount = goodsUVCountList.stream().mapToInt(ZStatisticsGoodsUVCount::getUvCount).sum();
        }
        resultMap.put("goodsUVCount",goodsUVCount);
        //操作类型
        resultMap.put("type",dateQueryCondition.getType());
        List<String> xList = new ArrayList<>();
        if(dateList.size() ==1){
            date24List.forEach(d->{
                xList.add(DateUtils.format(d,"yyyy-MM-dd HH"));
            });
        }else{
            dateList.forEach(d->{
                xList.add(DateUtils.format(d,"yyyy-MM-dd"));
            });
        }
        resultMap.put("xList",xList);
        return resultMap;
    }

    /**
     * 平台PV
     * @param type
     * @param timeSql
     * @param dateList
     * @param date24List
     * @return List<ZStatisticsPageViewCount>
     */
    private List<ZStatisticsPageViewCount> pageViewCountList(int type,
                                                             String timeSql,
                                                             List<Date> dateList,
                                                             List<Date> date24List){
        List<ZStatisticsPageViewCount> pageViewCountList = zStatisticsPageViewCountBiz.queryPageViewCountList(type,timeSql);
        List<Date> _dataList = new ArrayList<>();
        List<ZStatisticsPageViewCount> resultList =new ArrayList<>();
        StringBuilder TIME_F = new StringBuilder("yyyy-MM-dd");
        if(type==1){
            _dataList.addAll(date24List);
            TIME_F.delete(0,TIME_F.length());
            TIME_F.append("yyyy-MM-dd HH");
        }else{
            _dataList.addAll(dateList);
        }
        if(ObjectUtils.isNotEmpty(pageViewCountList)){
            Map<String,ZStatisticsPageViewCount> pageViewCountMap = pageViewCountList.stream().collect(Collectors.toMap(e->DateUtils.format(e.getRequestTime(),TIME_F.toString()),e->e));
            _dataList.forEach(date->{
                String key = DateUtils.format(date,TIME_F.toString());
                ZStatisticsPageViewCount pageViewCount = pageViewCountMap.get(key);
                if(pageViewCount==null){
                    pageViewCount = new ZStatisticsPageViewCount();
                    pageViewCount.setRequestTime(date);
                }
                resultList.add(pageViewCount);
            });
        }else{
            _dataList.forEach(date->{
                ZStatisticsPageViewCount pageViewCount= new  ZStatisticsPageViewCount();
                pageViewCount.setRequestTime(date);
                resultList.add(pageViewCount);
            });
        }
        return resultList;
    }

    /**
     * 平台UV
     * @param dateList
     * @param timeSql
     * @return List<ZStatisticsUniqueVisitorCount>
     */
    private List<ZStatisticsUniqueVisitorCount> uniqueVisitorCountList(List<Date> dateList,
                                                                       String timeSql){
        List<ZStatisticsUniqueVisitorCount> resultList = new ArrayList<>();
        //平台UV
        List<ZStatisticsUniqueVisitorCount> uniqueVisitorCountList = zStatisticsUniqueVisitorCountBiz.queryUniqueVisitorCountList(timeSql);
        if(ObjectUtils.isNotEmpty(uniqueVisitorCountList)){
            Map<String,ZStatisticsUniqueVisitorCount> uniqueVisitorCountMap = uniqueVisitorCountList.stream().collect(Collectors.toMap(e->DateUtils.format(e.getRequestTime(),"yyyy-MM-dd"),e->e));
            dateList.forEach(date->{
                String key = DateUtils.format(date,"yyyy-MM-dd");
                ZStatisticsUniqueVisitorCount uniqueVisitorCount = uniqueVisitorCountMap.get(key);
                if(uniqueVisitorCount==null){
                    uniqueVisitorCount = new ZStatisticsUniqueVisitorCount();
                    uniqueVisitorCount.setRequestTime(date);
                }
                resultList.add(uniqueVisitorCount);
            });
        }else{
            dateList.forEach(date->{
                ZStatisticsUniqueVisitorCount uniqueVisitorCount = new ZStatisticsUniqueVisitorCount();
                uniqueVisitorCount.setRequestTime(date);
                resultList.add(uniqueVisitorCount);
            });
        }
        return resultList;
    }

    /**
     * 商品PV
     * @param dateList
     * @param timeSql
     * @param date24List
     * @return List<ZStatisticsGoodsPVCount>
     */
    private List<ZStatisticsGoodsPVCount> goodsPVCountList(List<Date> dateList,String timeSql,List<Date> date24List){
        List<Date> _dateList = new ArrayList<>();
        List<ZStatisticsGoodsPVCount> resultList = new ArrayList<>();
        StringBuilder TIME_F = new StringBuilder("yyyy-MM-dd");
        //商品PV
        List<ZStatisticsGoodsPVCount> goodsPVCountList=null;
        if(dateList.size() > 1){
            _dateList.addAll(dateList);
            goodsPVCountList = zStatisticsGoodsPVCountBiz.queryGoodsPVCountList(timeSql);
        }else{
            TIME_F.delete(0,TIME_F.length());
            TIME_F.append("yyyy-MM-dd HH");
            _dateList.addAll(date24List);
            goodsPVCountList = zStatisticsGoodsPVCountBiz.find(" countTime='"+ DateUtils.format(dateList.get(0),"yyyy-MM-dd") +"'",null,null);
            if(ObjectUtils.isNotEmpty(goodsPVCountList)){
                TreeMap<String,Integer> _treeMap = new TreeMap<>();
                goodsPVCountList.forEach(e->{
                    String pvInfo = e.getPvInfo();
                    TreeMap<String,Object> treeMap = gson.fromJson(pvInfo, TreeMap.class);
                    treeMap.forEach((k,v)->{
                        Integer pvCount = _treeMap.get(k);
                        if(pvCount==null){
                            _treeMap.put(k,((Double)v).intValue());
                        }else{
                            _treeMap.put(k,pvCount + ((Double)v).intValue());
                        }
                    });
                });
                StringBuilder timeStr =new StringBuilder( DateUtils.format(dateList.get(0),"yyyy-MM-dd"));
                _treeMap.forEach((k,v)->{
                    ZStatisticsGoodsPVCount goodsPVCount = new ZStatisticsGoodsPVCount();
                    Date date = DateUtils.parseDate(timeStr.toString() + " "+k,"yyyy-MM-dd HH");
                    goodsPVCount.setCountTime(date);
                    goodsPVCount.setPvCount(v);
                    resultList.add(goodsPVCount);
                });
                return resultList;
            }
        }
        if(ObjectUtils.isNotEmpty(goodsPVCountList)){
            Map<String,List<ZStatisticsGoodsPVCount>> goodsPVCountListMap = goodsPVCountList.stream().collect(Collectors.groupingBy(e->DateUtils.format(e.getCountTime(),TIME_F.toString())));
            _dateList.forEach(date->{
                String key = DateUtils.format(date,TIME_F.toString());
                List<ZStatisticsGoodsPVCount> _goodsPVCountList = goodsPVCountListMap.get(key);
                ZStatisticsGoodsPVCount goodsPVCount = new ZStatisticsGoodsPVCount();
                if(ObjectUtils.isNotEmpty(_goodsPVCountList)){
                    int pvCount = _goodsPVCountList.stream().mapToInt(ZStatisticsGoodsPVCount::getPvCount).sum();
                    goodsPVCount.setPvCount(pvCount);
                }
                goodsPVCount.setCountTime(date);
                resultList.add(goodsPVCount);
            });
        }else{
            _dateList.forEach(date->{
                ZStatisticsGoodsPVCount goodsPVCount = new ZStatisticsGoodsPVCount();
                goodsPVCount.setCountTime(date);
                resultList.add(goodsPVCount);
            });
        }
        return resultList;
    }

    /**
     * 商品UV
     * @param dateList
     * @param timeSql
     * @return List<ZStatisticsGoodsUVCount>
     */
    private List<ZStatisticsGoodsUVCount> goodsUVCountList(List<Date> dateList,String timeSql){
        List<ZStatisticsGoodsUVCount> goodsUVCountList = zStatisticsGoodsUVCountBiz.queryGoodsSumUVCountList(timeSql);
        List<ZStatisticsGoodsUVCount> resultList = new ArrayList<>();
        if(ObjectUtils.isNotEmpty(goodsUVCountList)){
            Map<String,ZStatisticsGoodsUVCount> goodsUVCountMap = goodsUVCountList.stream().collect(Collectors.toMap(e->DateUtils.format(e.getCountTime(),"yyyy-MM-dd"),e->e));
            dateList.forEach(data->{
                String key = DateUtils.format(data,"yyyy-MM-dd");
                ZStatisticsGoodsUVCount goodsUVCount = goodsUVCountMap.get(key);
                if(goodsUVCount==null){
                    goodsUVCount = new ZStatisticsGoodsUVCount();
                    goodsUVCount.setCountTime(data);
                }
                resultList.add(goodsUVCount);
            });
        }else{
            dateList.forEach(date->{
                ZStatisticsGoodsUVCount goodsUVCount = new ZStatisticsGoodsUVCount();
                goodsUVCount.setCountTime(date);
                resultList.add(goodsUVCount);
            });
        }
        return resultList;
    }
}
